import base64
import re

import ujson

from django.core.cache import caches
from django.db.models import Q
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render, redirect
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django_redis import get_redis_connection

from polls.captcha import Captcha
from polls.models import Subject, Teacher, User
from polls.utils import make_sha256_digest, gen_verify_code, send_mobile_code, gen_mobile_code

TEL_PATTERN = re.compile(r'1[3-9]\d{9}')


def captcha(request):
    code_text = gen_verify_code()
    request.session['code'] = code_text.lower()
    image_data = Captcha.instance().generate(code_text)
    return HttpResponse(image_data, content_type='image/png')


def get_mobile_code(request, tel):
    # redis_cli = get_redis_connection()
    # redis_cli.rpush('items', 10, 20, 30, 40, 50, 60)
    if TEL_PATTERN.fullmatch(tel):
        if caches['default'].get(f'voteapp:polls:block:{tel}'):
            data = {'code': 20004, 'msg': '请不要在60秒以内重复发送短信验证码'}
        else:
            code = gen_mobile_code()
            result = send_mobile_code(tel, code)
            if result['error'] == 0:
                caches['default'].set(f'voteapp:polls:block:{tel}', code, 60)
                caches['default'].set(f'voteapp:polls:valid:{tel}', code, 600)
                data = {'code': 20000, 'msg': '短息发送成功!'}
            else:
                data = {'code': 20001, 'msg': '请重新发送短信验证码!'}
    else:
        data = {'code': 20003, 'msg': '请输入有效的手机号码!'}
    return JsonResponse(data)


@csrf_exempt
def login(request):
    hint = ''
    if request.method == 'GET':
        backurl = request.GET.get('backurl')
        backurl = base64.b64decode(backurl).decode() if backurl else '/'
    else:
        backurl = request.POST.get('backurl', '/')
        code_from_user = request.POST.get('captcha', '0')
        code_from_serv = request.session.get('code', '1')
        if code_from_user.lower() == code_from_serv:
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username and password:
                password = make_sha256_digest(password)
                # Q | Q ---> 或者
                # Q & Q ---> 而且
                # ~Q ---> 取反（not）
                user = User.objects.filter(
                    (Q(username=username) | Q(tel=username)) & Q(password=password)
                ).first()
                if user:
                    delta = timezone.now() - user.last_visit
                    if delta.days > 0:
                        user.last_visit = timezone.now()
                        user.save(insert=False)
                    # 如果用户登录成功，在用户专属的session对象中保存用户信息
                    request.session['userid'] = user.userid
                    request.session['username'] = user.username
                    return redirect(backurl)
                else:
                    hint = '用户名或密码错误'
            else:
                hint = '请提供有效的用户名和密码'
        else:
            hint = '请输入有效的验证码'
    return render(request, 'login.html', {'hint': hint, 'backurl': backurl})


def register(request):
    return render(request, 'register.html', {})


def logout(request):
    # 所谓的注销就是清除掉用户在自己的会话中保存的信息
    request.session.flush()
    return redirect('/')


def show_subjects(request):
    queryset = Subject.objects.all()
    return render(request, 'subjects.html', {'subjects': queryset})


def show_teachers(request):
    try:
        sno = int(request.GET.get('sno', '0'))
        subject = Subject.objects.filter(no=sno).first()
        if subject:
            queryset = Teacher.objects.filter(subject__no=sno)
            return render(
                request,
                'teachers.html',
                {'subject': subject, 'teachers': queryset}
            )
    except (KeyError, ValueError):
        pass
    return redirect('/')


def praise_or_criticize(request):
    if not request.is_ajax():
        return HttpResponse(status=405)
        return render(request, 'error.html')
    # request.session代表一个用户的会话
    # request.session类字典对象，可以用来保存每个用户专属的数据
    if not request.session.get('userid'):
        result = {'code': 10002, 'msg': '请先登录'}
    else:
        # request.path可以获取请求的路径
        is_praise = request.path == '/praise/'
        try:
            tno = int(request.GET.get('tno', '0'))
            teacher = Teacher.objects.get(no=tno)
            if is_praise:
                teacher.good_count += 1
            else:
                teacher.bad_count += 1
            teacher.save()
            result = {'code': 10000, 'msg': '操作成功',
                      'count': teacher.good_count if is_praise else teacher.bad_count}
        except (ValueError, Teacher.DoesNotExist):
            result = {'code': 10001, 'msg': '操作失败'}
    # 如果要向浏览器返回JSON格式数据，可以使用JsonResponse，参数是一个字典
    return JsonResponse(result)
